package gf

import (
	"crypto/md5"
	"fmt"
	"io"
	"os"
)

// GetFileMd5 计算并返回文件的MD5哈希值。
// 此方法首先确认当前对象是否为文件，然后尝试打开文件并计算其MD5哈希值。
// 如果在任一阶段遇到错误，方法将记录错误信息并返回空字符串。
func (fi *FileStatus) GetFileMd5() string {
	// 初始化错误信息
	fi.Err = nil

	// 检查当前对象是否为文件
	fi.IsFile()
	if !fi.IsFiles {
		// 如果当前对象不是文件，则记录错误信息并返回空字符串
		fi.Err = fmt.Errorf("当前对象不是一个文件: %s", fi.FileName)
		return ""
	}

	// 尝试打开文件
	fi.open, fi.Err = os.Open(fi.FileName)
	if fi.Err != nil {
		// 如果打开文件时发生错误，记录错误信息并返回空字符串
		return ""
	}

	// 确保文件在方法执行完毕后关闭
	defer func(open *os.File) {
		err := open.Close()
		if err != nil {
			// 如果关闭文件时发生错误，此处可以记录日志（可选）
			return
		}
	}(fi.open)

	// 创建MD5哈希对象
	hash := md5.New()

	// 将文件内容复制到哈希对象中
	if _, err := io.Copy(hash, fi.open); err != nil {
		// 如果复制过程中发生错误，记录错误信息并返回空字符串
		fi.Err = err
		return ""
	}

	// 获取MD5哈希的前16位并返回其十六进制表示
	hashInBytes := hash.Sum(nil)[:16]
	return fmt.Sprintf("%x", hashInBytes)
}

// GetFileMd5 计算并返回指定文件的MD5值。
// 参数:
//
//	filename - 要计算MD5值的文件名（字符串类型）。
//
// 返回值:
//
//	文件的MD5值（字符串类型）。如果文件不存在或读取失败，返回值可能为空或错误信息。
//
// 示例:
//
//	filename := "example.txt"
//	md5Value := GetFileMd5(filename)
//	fmt.Println(md5Value) // 输出: d41d8cd98f00b204e9800998ecf8427e
func GetFileMd5(filename string) string {
	return NewFile(filename).GetFileMd5()
}
